package review

import "fmt"

//实现观察者模式
//1.定义主题和观察者接口 主题方法包括 1.1添加观察者 1.2通知观察者 1.3减少观察者
//2.有两个结构体分别去实现这两个接口里面的方法
//3.主题中去添加观察者 使用slice去存储
//案例：银行是主题 人是观察者 银行通知人去还钱

type Subject interface {
	AddObserver(observer Observer)
	SubObserver(observer Observer)
	NotifyAll(msg string)
}

type Observer interface {
	DoWork(msg string)
}

type Bank struct {
	observers []Observer
}

func NewBank() *Bank {
	return &Bank{}
}

func (b *Bank) AddObserver(observer Observer) {
	b.observers = append(b.observers, observer)
}

func (b *Bank) SubObserver(observer Observer) {
	for i, obs := range b.observers {
		if observer == obs {
			b.observers = append(b.observers[:i], b.observers[i+1:]...)
		}
	}
}

func (b *Bank) NotifyAll(msg string) {
	for _, observer := range b.observers {
		observer.DoWork(msg)
	}
}

type ZhangSan struct {
	name string
}

func NewZhangSan(name string) *ZhangSan {
	return &ZhangSan{name: name}
}

func (z ZhangSan) DoWork(msg string) {
	fmt.Println(z.name + msg)
}

type LiSi struct {
	name string
}

func NewLiSi(name string) *LiSi {
	return &LiSi{name: name}
}

func (l LiSi) DoWork(msg string) {
	fmt.Println(l.name + msg)
}

type WangWu struct {
	name string
}

func NewWangWu(name string) *WangWu {
	return &WangWu{name: name}
}

func (w WangWu) DoWork(msg string) {
	fmt.Println(w.name + msg)
}
